package com.juyu.miliao.scheduler.controller;

import com.alibaba.fastjson.JSONObject;
import com.juyu.miliao.common.netease.NetEaseCloudUserService;

import com.juyu.miliao.scheduler.dao.mysql.UserInfoDao;
import com.juyu.miliao.scheduler.domin.User;
import lombok.extern.slf4j.Slf4j;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * wbf
 */
@Slf4j
@RestController
public class TestController {

    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private ThreadPoolExecutor updateUserIconThreadPoolExecutor;

    private final Logger loggerInfo = LoggerFactory.getLogger("userUpdateIconInfo");
    private final Logger loggerError = LoggerFactory.getLogger("userUpdateIconError");
    //线程池数量
    private static final int poolNumber = 8;

    @GetMapping(value = "/testNetEase/updateUserInfoIcon")
    public JSONObject updateUserInfoIcon(HttpServletRequest request, int page) {
        loggerInfo.info("开始任务：");
        JSONObject json = new JSONObject();
        int j = page;
        long userCount = 0L;
        int count = 0;
        long sum = 0L;
        try {
            //获取要处理的数量总量
            userCount = userInfoDao.getUserInfoCount();
            //计算要循环多少次能够执行完成
            sum = userCount / 5000 + 1;
            for (int i = page; i <= sum; i++) {
                loggerInfo.info("正在进行页数："+i);
                loggerInfo.info("总页数："+sum);
                loggerInfo.info("已处理数据数："+count);
                loggerInfo.info("总数据数量："+userCount);
                CountDownLatch latch = new CountDownLatch(poolNumber);
                //计算分页
                int startNum = getOffset(i, 5000);
                List<User> userList = userInfoDao.getUserListByUpdateIcon(startNum, startNum + 5000 - 1);
                if (userList == null || userList.size() == 0) {
                    break;
                }
                //将原list拆分成8个，分别执行
                List<List<User>> uList = averageAssign(userList, poolNumber);
                uList.forEach(k -> {
                    updateUserIconThreadPoolExecutor.execute(new RunnableWrapper(() -> {
                        updateUserIcon(k, latch);
                    }));
                });
                latch.await();
                count += userList.size();
                j++;
            }
            loggerInfo.info("任务正常结束：");
            loggerInfo.info("执行条数count："+count);
            loggerInfo.info("总条数userCount："+userCount);
            loggerInfo.info("总页数sum："+sum);
            loggerInfo.info("执行页数page："+page);
            json.put("count", count);//执行条数
            json.put("userCount", userCount);//总条数
            json.put("sum", sum);//执行了多少页
            json.put("page", j);//执行了多少页
            return json;

        } catch (Exception e) {
            loggerInfo.info("任务异常结束：");
            loggerInfo.info("执行条数count："+count);
            loggerInfo.info("总条数userCount："+userCount);
            loggerInfo.info("总页数sum："+sum);
            loggerInfo.info("执行页数page："+j);
            loggerInfo.info("异常msg："+e.toString());
            json.put("count", count);//执行条数
            json.put("userCount", userCount);//总条数
            json.put("sum", sum);//执行了多少页
            json.put("page", j);//执行了多少页
            json.put("msg", e.toString());
            return json;
        }
    }

    private void updateUserIcon(List<User> userList, CountDownLatch latch) {
        try {
            userList.forEach(user -> {
                if (user.getIcon() != null && !user.getIcon().equals("null") && !user.getIcon().equals("")) {
                    String createLogInfo = null;
                    try {
                        createLogInfo = NetEaseCloudUserService.
                                updateUserInfo(user.getUserId(), user.getNickName(), user.getIcon());
                        if (!createLogInfo.substring(createLogInfo.indexOf("code") + 6,
                                createLogInfo.indexOf("code") + 9)
                                .equals("200")) {
                            loggerInfo.info(user.getUserId() + "");
                        }
                    } catch (IOException e) {
                        loggerInfo.info(user.getUserId() + "");
                        loggerError.error(e.getMessage());
                    }
                }
            });
        } finally {
            latch.countDown();
        }

    }

    public class RunnableWrapper implements Runnable {
        private final Runnable runnable;

        public RunnableWrapper(Runnable runnable) {
            this.runnable = runnable;
        }

        @Override
        public void run() {
            try {
                runnable.run();
            } catch (Exception e) {
                loggerError.error(e.getMessage());
            }
        }

    }

    private static <User> List<List<User>> averageAssign(List<User> list, int n) {
        List<List<User>> result = new ArrayList<>();
        int remaider = list.size() % n;  //(先计算出余数)
        int number = list.size() / n;  //然后是商
        int offset = 0;//偏移量
        for (int i = 0; i < n; i++) {
            List<User> value = null;
            if (remaider > 0) {
                value = list.subList(i * number + offset, (i + 1) * number + offset + 1);
                remaider--;
                offset++;
            } else {
                value = list.subList(i * number + offset, (i + 1) * number + offset);
            }
            result.add(value);
        }
        return result;
    }


    private static int getOffset(int pageNumber, int pageSize) {
        return (pageNumber - 1) * pageSize;
    }

}
